from bson import ObjectId
from datetime import datetime

OBJ_ID = "id"
FIELD_ID = "_id"

def check_value(value, type):
    if value==None:
        raise Exception("值不能为空")
    if not isinstance(value, type):
        raise Exception(f"{value}类型错误，应该为{type}") 
class ReturnObjct(object):
    ##返回的对象
    def __init__(self):
        self.code = 0
        self.msg = 'ok'
    def to_json(self):
        return {"code":self.code, "msg":self.msg}
def read_id(obj):
    _id = obj.get(FIELD_ID)
    if _id!=None:
        return str(_id)
    _id = obj.get(OBJ_ID)
    if _id!=None:
        return str(_id)
    return None

class Session(object):
    #会话对象
    COLL_NAME = "sessions"
    INDEX_SESSION = "session_index"
    FIELD_TOKEN = "token"
    FIELD_OBJ_ID = "obj_id" #对象id
    FIELD_OBJ_TYPE = "obj_type" #对象类型
    FIELD_LAST_ACTIVE = "last_active"
    
    TIME_OUT_SECONDS = 300
    
    OT_DEVICE = 1
    OT_USER = 2
    
    def __init__(self):
        self._id = None
        self.obj_id = None #对象id，device或user的id
        self.token = None #对象令牌
        self.obj_type = None
        #最后活动时间，因为Mongodb用的是UTC时间，所以这个地方要指定utc时区
        self.last_active = None
    
    def update(self):
        self.last_active = datetime.utcnow()
        
    def new_token(self):
        self.token = str(ObjectId())
        
    def to_json(self):
        return {OBJ_ID: self._id,
                Session.FIELD_TOKEN:self.token,
                Session.FIELD_OBJ_ID: self.obj_id,
                Session.FIELD_OBJ_TYPE: self.obj_type,
                Session.FIELD_LAST_ACTIVE: self.last_active}
    def from_json(self, data: dict):
        self._id = read_id(data)
        self.token = data.get(Session.FIELD_TOKEN)
        self.obj_id = data.get(Session.FIELD_OBJ_ID)
        self.obj_type = data.get(Session.FIELD_OBJ_TYPE)
        self.last_active = data.get(Session.FIELD_LAST_ACTIVE)

class Device(object):
    #设备
    COLL_NAME = "devices"
    FIELD_NAME = "name" #设备名称，激活或修改时设置
    FIELD_ENABLE = "enable" #是否可用
    FIELD_KEY = "key" #设备的key，用于设备连接服务验证设备身份
    FIELD_ACTIVE_CODE = "active_code" #设备的激活码
    FIELD_OWER = "owner" #设备的拥有者，激活设备的用户的id
    FIELD_TYPE = "type" #设备类型
    FIELD_TIME = "time" #激活时间
    types = {
        "pet_feeder": {
            "dtid": "pet_feeder",
            "name": "宠物喂食器",
            "icon_url": "cat_feeder.png"
        }
    }    
    def __init__(self):
        self._id = None
        self.key = None
        self.name = None
        self.enable = None
        self.owner = None
        self.active_code = None
        self.type = None
        self.time = None
    def to_json(self):
        return {OBJ_ID: self._id,
                Device.FIELD_KEY: self.key,
                Device.FIELD_NAME: self.name,
                Device.FIELD_TYPE: self.type,
                Device.FIELD_ENABLE: self.enable,
                Device.FIELD_OWER: self.owner,
                Device.FIELD_ACTIVE_CODE: self.active_code,
                Device.FIELD_TIME: self.time}
    
    def from_json(self, data: dict):
        self._id = read_id(data)
        self.type = data.get(Device.FIELD_TYPE)
        self.key = data.get(Device.FIELD_KEY)
        self.name = data.get(Device.FIELD_NAME)
        self.owner = data.get(Device.FIELD_OWER)
        self.active_code = data.get(Device.FIELD_ACTIVE_CODE)
        self.enable = data.get(Device.FIELD_ENABLE)
        self.time = data.get(Device.FIELD_TIME)
    @classmethod
    def get_type_data(cls, dtid):
        if(dtid):
            return cls.types.get(dtid)
        return None

class User(object):
    #用户
    COLL_NAME = "users"
    FIELD_NAME = "name"
    FIELD_PWD = "pwd"
    FIELD_DEVICES = "devices"
    def __init__(self):
        self._id = None #id
        self.name = None #登录名
        self.pwd = None #用户密码
        self.devices = [] #用户关联的设备
    def to_json(self):
        return {OBJ_ID: self._id,
                User.FIELD_NAME: self.name, 
                User.FIELD_PWD: self.pwd,
                User.FIELD_DEVICES: self.devices}
    def add_device(self, device_id: str):
        if self.devices==None:
            self.devices = []
        if not device_id in self.devices:
            self.devices.append(device_id)
    def from_json(self, data: dict):
        self._id = read_id(data)
        self.name = data.get(User.FIELD_NAME)
        self.pwd = data.get(User.FIELD_PWD)
        self.devices = data.get(User.FIELD_DEVICES)

class MessageData(object):
    COLL_NAME = "message_data"
    SENDER_DEVICE = 'device'
    SENDER_USER = 'user'
    FIELD_DEVICE_ID = "device_id"
    FIELD_SENDER = "sender"
    FIELD_ACTION = "action"
    FIELD_TIME = "time"
    FIELD_DATA = "data"

    def __init__(self) -> None:
        self._id = None #消息ID
        self.sender = None #消息发送方，设备或人员
        self.device_id = None #设备_ID
        self.action = None #动作，由发送方和接收方自己来确定
        self.data = None #消息的数据
        self.time = None #消息时间
        pass
    @classmethod
    def check_sender(cls, sender: str)->bool:
        return sender in [MessageData.SENDER_DEVICE, MessageData.SENDER_USER]
    def check_data(self):
        check_value(self._id, str)
        check_value(self.sender, str)
        check_value(self.device_id, str)
        check_value(self.action, str)
    def to_json(self):
        return {OBJ_ID: self._id,
                MessageData.FIELD_DEVICE_ID: self.device_id, 
                MessageData.FIELD_SENDER: self.sender,
                MessageData.FIELD_ACTION: self.action,
                MessageData.FIELD_TIME: self.time,
                MessageData.FIELD_DATA: self.data}
    
    def from_json(self, data: dict):
        self._id = read_id(data)
        self.action = data.get(MessageData.FIELD_ACTION)
        self.time = data.get(MessageData.FIELD_TIME)
        self.device_id = data.get(MessageData.FIELD_DEVICE_ID)
        self.sender = data.get(MessageData.FIELD_SENDER)
        self.data = data.get(MessageData.FIELD_DATA)

if __name__== "__main__":
    check_value(None, int)